#include <stdio.h>
#include <string.h>
#include "my_can.h"

CAN_TxHeaderTypeDef can_TxHeader;
CAN_FilterTypeDef Filter;

void vApp_CAN_TxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pTxHeader, uint32_t Stdid, uint8_t *aData, uint8_t DLC)
{
    uint32_t Tx_MailBox;
    pTxHeader->DLC = DLC;
    pTxHeader->StdId = Stdid;
    if (HAL_CAN_AddTxMessage(hcan, pTxHeader, aData, &Tx_MailBox) != HAL_OK)
    {
        Error_Handler();
    }
}
uint8_t vApp_CAN_TxMessage2(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pTxHeader, uint32_t Stdid, uint8_t *aData, uint8_t DLC)
{
    uint32_t Tx_MailBox;
    pTxHeader->DLC = DLC;
    pTxHeader->StdId = Stdid;
    if (HAL_CAN_AddTxMessage(hcan, pTxHeader, aData, &Tx_MailBox) != HAL_OK)
    {
       return 1;
    }
  return 0;
}

void vApp_CAN_TxHeader_Init(CAN_TxHeaderTypeDef *pHeader,
                            uint32_t StdId,
                            uint32_t ExtId,
                            uint32_t IDE,
                            uint32_t RTR,
                            uint32_t DLC)
{
    pHeader->StdId = StdId; //11�?????     标准标识�?????
    pHeader->ExtId = ExtId; //29�?????     扩展标识�?????
    pHeader->IDE = IDE;     //1�?????        0:标准�????? 1:拓展�?????
    pHeader->RTR = RTR;     //1�?????   0:数据�????? 1:远程�?????
    pHeader->DLC = DLC;     //4�?????   发�?�的数据的长�?????
    pHeader->TransmitGlobalTime = ENABLE;
}
void vApp_CAN_Filter_Init(CAN_FilterTypeDef *pFilter,
                          uint32_t IdHigh,
                          uint32_t IdLow,
                          uint32_t MaskIdHigh,
                          uint32_t MaskIdLow,
                          uint32_t FIFOAssignment,
                          uint32_t Bank,
                          uint32_t Mode,
                          uint32_t Scale,
                          uint32_t Activation,
                          uint32_t SlaveStartFilterBank)
{
    pFilter->FilterIdHigh = 0;
    pFilter->FilterIdLow = 0;
    pFilter->FilterMaskIdHigh = 0xffff;
    pFilter->FilterMaskIdLow = 0xffff;
    pFilter->FilterFIFOAssignment = CAN_FILTER_FIFO0;
    pFilter->FilterBank = 0;                      //第零组滤波器
    pFilter->FilterMode = CAN_FILTERMODE_IDMASK;  //滤波器模式
    pFilter->FilterScale = CAN_FILTERSCALE_32BIT; //滤波器位数
    pFilter->FilterActivation = ENABLE;
    pFilter->SlaveStartFilterBank = 0; //第0组滤波器第0个滤波器
}
//标准帧滤波器初始化
void vApp_CAN_Filter_Init_IDMASK(CAN_FilterTypeDef *pFilter,
                                 uint32_t Bank, //滤波器编号
                                 uint32_t id    //允许通过的ID，0的时候允许所有
)
{

    pFilter->FilterIdHigh = id << 5;
    pFilter->FilterIdLow = 0;
    if (id != 0)
    {
        pFilter->FilterMaskIdHigh = 0xfff0; //标准帧只需要比较前面11位
    }
    else
    {
        pFilter->FilterMaskIdHigh = 0x0; //不比较任何一位
    }

    pFilter->FilterMaskIdLow = 0;
    pFilter->FilterFIFOAssignment = CAN_FILTER_FIFO0;
    pFilter->FilterBank = Bank;                   //滤波器编号0-13
    pFilter->FilterMode = CAN_FILTERMODE_IDMASK;  //滤波器模式
    pFilter->FilterScale = CAN_FILTERSCALE_32BIT; //滤波器位数
    pFilter->FilterActivation = ENABLE;
    pFilter->SlaveStartFilterBank = 14; //分配滤波器从属关系，0-can1，can2共享所有滤波器，
                                        /* 对于单个CAN实例，此参数毫无意义。
                                       对于双CAN实例，所有索引较低的滤波器组都分配给主
                                       CAN实例，而所有索引较大的滤波器组都分配给从属
                                       CAN实例。
                                       此参数必须是介于Min_Data = 0和Max_Data = 27之间的数字*/
}

void CAN_Filter_set(CAN_HandleTypeDef *phcan,
                    CAN_FilterTypeDef *pFilter,
                    uint32_t Bank, //滤波器编号
                    uint32_t id    //允许通过的ID，0的时候允许所有

)
{
    vApp_CAN_Filter_Init_IDMASK(pFilter, Bank, id);
    HAL_CAN_ConfigFilter(phcan, pFilter);
}
void CAN_StarCAN(CAN_HandleTypeDef *hcan)
{

    // pHeader->StdId = 0x15; //11位标准帧id
    // pHeader->ExtId = 0; //29位扩展帧id
    // pHeader->IDE = 0;     //0标准帧 1扩展帧
    // pHeader->RTR = 0;     //0数据帧，1远程帧
    // pHeader->DLC = 0;     //数据帧长
    // pHeader->TransmitGlobalTime = ENABLE;
    /*-3- 启动CAN ---------------------------------------------------*/
    if (HAL_CAN_Start(hcan) != HAL_OK)
        Error_Handler();

    printf("can star is ok\n");
    /*-4- 使能中断通知 ----------------------------------------------*/
    if (HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
    {
        Error_Handler();
    }
}

//这里面主要写回调函数的处理过程，一般来说是用来缓存数据
//*********************************************callback*************************************************

extern CAN_HandleTypeDef can1_hand;
extern CAN_HandleTypeDef can2_hand;
CAN_RxHeaderTypeDef can_RxHeader;
uint8_t can_RxData[8];

void printfdata(uint8_t *can_Data)
{
    uint8_t L = can_RxHeader.DLC;
    uint8_t buff[8];
    for (size_t i = 0; i < 8; i++)
    {
        buff[i] = can_Data[i];
    }
    printf("[");
    for (size_t i = 0; i < L; i++)
    {
        printf("%X ", buff[i]);
    }
    printf("]\n");
}


void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcanhandle)
{
    UNUSED(hcanhandle);
    if (HAL_CAN_GetRxMessage(hcanhandle, CAN_FILTER_FIFO0, &can_RxHeader, can_RxData) == HAL_OK)
    {
        if (hcanhandle->Instance == CAN1)
        {
            Processing_CAN1(can_RxHeader,can_RxData);
        }
    }
}

void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
{
    UNUSED(hcan);
    if (hcan->Instance == CAN1)
        printf("can 1 error%ld  == %d\n", hcan->ErrorCode, hcan->State);
}